home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 …ember: Reference Library / Apple Developer Reference Library (December 1999) (Disk 1).iso / pc / technical documentation / develop / develop issue 26 / develop issue 26 code / qd3d custom attributes / draft quickdraw 3d technotes / cattrs from developers / microspot custom attributes / customattribute.cp next >
Encoding:
Text File  |  1996-03-22  |  34.2 KB  |  1,219 lines

  1. // ===========================================================================
  2. //    Project : QuickDraw 3D
  3. //    File    : CustomAttribute.cp
  4. //
  5. //    Authors : Robin Landsbert
  6. //        
  7. // ===========================================================================
  8.  
  9.  
  10. #include "CustomAttribute.h"
  11. #include <QD3DIO.h>
  12. #include <QD3DString.h>
  13. #include <string.h>
  14.  
  15.  
  16. TQ3FunctionPointer HandleRecordMetaHandler ( TQ3MethodType methodType , TQ3FunctionPointer ReadData ) ;
  17. TQ3FunctionPointer NameMetaHandler ( TQ3MethodType methodType ) ;
  18. TQ3FunctionPointer FourByteMetaHandler ( TQ3MethodType methodType ) ;
  19. TQ3FunctionPointer DoubleMetaHandler ( TQ3MethodType methodType ) ;
  20. TQ3FunctionPointer UpVectorAttributeMetaHandler ( TQ3MethodType methodType ) ;
  21. TQ3FunctionPointer ForwardDirectionAttributeMetaHandler ( TQ3MethodType methodType ) ;
  22. TQ3FunctionPointer W3AnchorMetaHandler ( TQ3MethodType methodType ) ;
  23. TQ3FunctionPointer W3InlineMetaHandler ( TQ3MethodType methodType ) ;
  24. TQ3FunctionPointer WWWAnchorMetaHandler( TQ3MethodType methodType ) ;
  25.  
  26. bool        DoHandleReadData ( THandleRecord& theHandleRec , TQ3FileObject file ) ;
  27. TQ3Status    HandleTraverse ( TQ3Object object , THandleRecord* data , TQ3ViewObject view ) ;
  28. TQ3Status    HandleWrite ( const THandleRecord* object , TQ3FileObject file ) ;
  29.  
  30. TQ3Status    HandleCopyAdd ( const THandleRecord* fromAPIElement , THandleRecord* toInternalElement ) ;
  31. TQ3Status    HandleCopyReplace ( const THandleRecord* fromAPIElement , THandleRecord* toInternalElement ) ;
  32. TQ3Status    HandleCopyDuplicate ( const THandleRecord* fromInternalElement , THandleRecord* toInternalElement ) ;
  33. TQ3Status    HandleDelete ( THandleRecord* internalElement ) ;
  34.  
  35. TQ3Status    FourByteTraverse ( TQ3Object object , unsigned long* data , TQ3ViewObject view ) ;
  36. TQ3Status    FourByteWrite ( const unsigned long* data , TQ3FileObject file ) ;
  37. TQ3Status    FourByteRead ( TQ3Object parentObject , TQ3FileObject file ) ;
  38. TQ3Status    FourByteCopy ( const unsigned long* fromAPIElement , unsigned long* toInternalElement ) ;
  39.  
  40. TQ3Status    DoubleTraverse ( TQ3Object object , TQ3Float64* data , TQ3ViewObject view ) ;
  41. TQ3Status    DoubleWrite ( const TQ3Float64* data , TQ3FileObject file ) ;
  42. TQ3Status    DoubleRead ( TQ3SetObject attributeSet , TQ3FileObject file ) ;
  43. TQ3Status    DoubleCopy ( const double* fromAPIElement , double* toInternalElement ) ;
  44.  
  45. TQ3FunctionPointer SoundMetaHandler ( TQ3MethodType methodType ) ;
  46. TQ3Status SoundReadData ( TQ3SetObject parentObject , TQ3FileObject file ) ;
  47.  
  48. TQ3FunctionPointer PictMetaHandler ( TQ3MethodType methodType ) ;
  49. TQ3Status PictReadData ( TQ3SetObject parentObject , TQ3FileObject file ) ;
  50.  
  51. TQ3FunctionPointer TextMetaHandler ( TQ3MethodType methodType ) ;
  52. TQ3Status TextReadData ( TQ3SetObject parentObject , TQ3FileObject file ) ;
  53.  
  54. TQ3FunctionPointer MovieMetaHandler ( TQ3MethodType methodType ) ;
  55. TQ3Status MovieReadData ( TQ3SetObject parentObject , TQ3FileObject file ) ;
  56.  
  57. TQ3FunctionPointer DescriptionMetaHandler ( TQ3MethodType methodType ) ;
  58. TQ3Status DescriptionReadData ( TQ3SetObject parentObject , TQ3FileObject file ) ;
  59.  
  60. TQ3Status HandleNameTraverse ( TQ3Object /*object*/ , TQ3Object* theStringObj , TQ3ViewObject theView ) ;
  61. TQ3Status HandleNameWrite ( const char* data , TQ3FileObject file ) ;
  62. TQ3Status HandleNameReadData ( TQ3SetObject parentObject , TQ3FileObject file ) ;
  63. TQ3Status HandleNameCopyAdd ( const TQ3Object* fromAPIElement , TQ3Object* toInternalElement ) ;
  64. TQ3Status HandleNameCopyReplace ( const TQ3Object* fromAPIElement , TQ3Object* toInternalElement ) ;
  65. TQ3Status HandleNameDelete ( TQ3Object* internalElement ) ;
  66.  
  67. TQ3Status VectorTraverse ( TQ3Object , TQ3Vector3D* upVector , TQ3ViewObject view ) ;
  68. TQ3Status VectorWrite ( const TQ3Vector3D* upVector , TQ3FileObject file ) ;
  69. TQ3Status UpVectorAttributeReadData ( TQ3SetObject attributeSet , TQ3FileObject file ) ;
  70. TQ3Status ForwardDirectionAttributeReadData ( TQ3SetObject attributeSet , TQ3FileObject file ) ;
  71.  
  72. TQ3Status W3AnchorTraverse ( TQ3Object , W3AnchorData* URLdata , TQ3ViewObject view ) ;
  73. TQ3Status W3AnchorWrite ( const W3AnchorData* URLdata , TQ3FileObject file ) ;
  74. TQ3Status W3AnchorReadData ( TQ3SetObject set , TQ3FileObject file ) ;
  75. TQ3Status W3AnchorCopyAdd ( const W3AnchorData* src , W3AnchorData* dst ) ;
  76. TQ3Status W3AnchorCopyReplace ( const W3AnchorData* src , W3AnchorData* dst ) ;
  77. TQ3Status W3AnchorDelete ( W3AnchorData* URLData ) ;
  78.  
  79. TQ3Status W3InlineTraverse ( TQ3Object , W3InlineData* inlineData , TQ3ViewObject view ) ;
  80. TQ3Status W3InlineWrite ( const W3InlineData* inlineData , TQ3FileObject file ) ;
  81. TQ3Status W3InlineReadData ( TQ3SetObject set , TQ3FileObject file ) ;
  82. TQ3Status W3InlineCopyAdd ( const W3InlineData* src , W3InlineData* dst ) ;
  83. TQ3Status W3InlineCopyReplace ( const W3InlineData* src , W3InlineData* dst ) ;
  84. TQ3Status W3InlineDelete ( W3InlineData* src ) ;
  85.  
  86. TQ3Status WWWAnchorTraverse ( TQ3Object , WWWAnchorData* wwwdata , TQ3ViewObject view ) ;
  87. TQ3Status WWWAnchorWrite ( const WWWAnchorData *wwwdata , TQ3FileObject file ) ;
  88. TQ3Status WWWAnchorReadData ( TQ3SetObject set , TQ3FileObject file ) ;
  89. TQ3Status WWWAnchorCopyAdd ( const WWWAnchorData* src , WWWAnchorData* dst ) ;
  90. TQ3Status WWWAnchorCopyReplace ( const WWWAnchorData* src , WWWAnchorData* dst ) ;
  91. TQ3Status WWWAnchorDelete ( WWWAnchorData* src ) ;
  92.  
  93.  
  94. // ===========================================================================
  95.  
  96.  
  97. void UnregisterCustomAttribute ( TQ3ObjectClass theClass )
  98.     {
  99.     Q3ObjectClass_Unregister ( theClass ) ;
  100.     }
  101.  
  102.  
  103. TQ3ObjectClass RegisterCustomAttribute ( TQ3AttributeType theType , unsigned long theSize , TQ3MetaHandler theHandler )
  104.     {
  105.     TQ3ObjectClass theClass ;
  106.     switch ( theType )
  107.         {
  108.         case kCustomSoundType:
  109.             theClass = Q3AttributeClass_Register ( theType , "Microspot:Sound" , theSize , theHandler ) ;
  110.             break ;
  111.         case kCustomPictType:
  112.             theClass = Q3AttributeClass_Register ( theType , "Microspot:Picture" , theSize , theHandler ) ;
  113.             break ;
  114.         case kCustomTextType:
  115.             theClass = Q3AttributeClass_Register ( theType , "Microspot:Text" , theSize , theHandler ) ;
  116.             break ;
  117.         case kCustomMovieType:
  118.             theClass = Q3AttributeClass_Register ( theType , "Microspot:Movie" , theSize , theHandler ) ;
  119.             break ;
  120.         case kLockedAttribute:
  121.             theClass = Q3AttributeClass_Register ( theType , "Microspot:Locked" , theSize , theHandler ) ;
  122.             break ;
  123.         case kUnitsAttribute:
  124.             theClass = Q3AttributeClass_Register ( theType , "Microspot:Units" , theSize , theHandler ) ;
  125.             break ;
  126.         case kScaleAttribute:
  127.             theClass = Q3AttributeClass_Register ( theType , "Microspot:Scale" , theSize , theHandler ) ;
  128.             break ;
  129.         case kNameAttribute:
  130.             theClass = Q3AttributeClass_Register ( theType , "Microspot:Name" , theSize , theHandler ) ;
  131.             break ;
  132.         case kDescriptionAttribute:
  133.             theClass = Q3AttributeClass_Register ( theType , "Microspot:Description" , theSize , theHandler ) ;
  134.             break ;
  135.         case kUpVectorAttribute:
  136.             theClass = Q3AttributeClass_Register ( theType , "Microspot:UpVector" , theSize , theHandler ) ;
  137.             break ;
  138.         case kForwardDirectionAttribute:
  139.             theClass = Q3AttributeClass_Register ( theType , "Microspot:ForwardVector" , theSize , theHandler ) ;
  140.             break ;
  141.         case kW3AnchorAttribute:
  142.             theClass = Q3AttributeClass_Register ( theType , "Microspot:W3Anchor" , theSize , theHandler ) ;
  143.             break ;
  144.         case kW3InlineAttribute:
  145.             theClass = Q3AttributeClass_Register ( theType , "Microspot:W3Inline" , theSize , theHandler ) ;
  146.             break ;
  147.         case kElementTypeWWWAnchor:
  148.             theClass = Q3AttributeClass_Register ( theType , "Microspot:WWWAnchor" , theSize , theHandler ) ;
  149.             break ;
  150.         default:
  151.             theClass = Q3AttributeClass_Register ( theType , "Microspot:UnknownAttribute" , theSize , theHandler ) ;
  152.             break ;
  153.         }
  154.     return theClass ;
  155.     }
  156.  
  157.  
  158. TQ3FunctionPointer HandleRecordMetaHandler ( TQ3MethodType methodType , TQ3FunctionPointer ReadData )
  159.     {
  160.     switch ( methodType )
  161.         {
  162.         case kQ3MethodTypeObjectTraverse:
  163.             return (TQ3FunctionPointer)HandleTraverse ;
  164.             
  165.         case kQ3MethodTypeObjectWrite:
  166.             return (TQ3FunctionPointer)HandleWrite ;
  167.             
  168.         case kQ3MethodTypeObjectReadData:
  169.             return ReadData ;
  170.             
  171.         case kQ3MethodTypeElementCopyAdd:
  172.         case kQ3MethodTypeElementCopyGet:
  173.         case kQ3MethodTypeElementCopyDuplicate:
  174.             return (TQ3FunctionPointer)HandleCopyAdd ;
  175.             
  176.         case kQ3MethodTypeElementCopyReplace:
  177.             return (TQ3FunctionPointer)HandleCopyReplace ;
  178.             
  179.         case kQ3MethodTypeElementDelete:
  180.             return (TQ3FunctionPointer)HandleDelete ;
  181.  
  182.         default:
  183.             return nil ;
  184.         } // switch
  185.     }
  186.  
  187.  
  188. TQ3Status HandleTraverse ( TQ3Object , THandleRecord* object , TQ3ViewObject theView )
  189.     {
  190.     if ( object )
  191.         {
  192.         if ( object->theHandle )
  193.             {
  194.             unsigned long theSize = GetHandleSize ( object->theHandle ) + sizeof ( long ) ; // + 4 for length
  195.             theSize = Q3Size_Pad ( theSize ) ;
  196.             return Q3View_SubmitWriteData ( theView , theSize , object , nil ) ;
  197.             }
  198.         }
  199.     return kQ3Success ;
  200.     }
  201.  
  202.  
  203. TQ3Status HandleWrite ( const THandleRecord* object , TQ3FileObject file )
  204.     {
  205.     if ( object )
  206.         {
  207.         if ( object->theHandle )
  208.             {
  209.             HLock ( object->theHandle ) ;
  210.             unsigned long size = Q3Size_Pad ( object->theSize ) ;
  211.             TQ3Status err = Q3Uns32_Write ( object->theSize , file ) ;
  212.             if ( err == kQ3Success )
  213.                 err = Q3RawData_Write ( ((unsigned char*)(*object->theHandle)) , size , file ) ;
  214.             HUnlock ( object->theHandle ) ;
  215.             return err ;
  216.             }
  217.         }
  218.     return kQ3Success ;
  219.     }    
  220.  
  221.  
  222. bool DoHandleReadData ( THandleRecord& theHandleRec , TQ3FileObject file )
  223.     {
  224.     if ( file == nil )
  225.         return false ;
  226.     TQ3Status err ;
  227.     err = Q3Uns32_Read ( &theHandleRec.theSize , file ) ;
  228.     if ( err == kQ3Failure )
  229.         return false ;
  230.  
  231.     unsigned long size = Q3Size_Pad ( theHandleRec.theSize ) ;
  232.     theHandleRec.theHandle = NewHandleClear ( size ) ;
  233.     if ( theHandleRec.theHandle )
  234.         {
  235.         HLock ( theHandleRec.theHandle ) ;
  236.         err = Q3RawData_Read ( ((unsigned char*)(*theHandleRec.theHandle)) , size , file ) ;
  237.         if ( err == kQ3Failure )
  238.             {
  239.             DisposeHandle ( theHandleRec.theHandle ) ;
  240.             theHandleRec.theHandle = nil ;
  241.             theHandleRec.theSize = 0 ;
  242.             return false ;
  243.             }
  244.         else
  245.             HUnlock ( theHandleRec.theHandle ) ;
  246.         return true ;
  247.         }
  248.     else
  249.         return false ;
  250.     }
  251.     
  252.     
  253. TQ3Status HandleCopyAdd ( const THandleRecord* fromAPIElement , THandleRecord* toInternalElement )
  254.     {
  255.     if ( fromAPIElement && toInternalElement )
  256.         {
  257.         long theSize = fromAPIElement->theSize ;
  258.         if ( theSize )
  259.             {
  260.             toInternalElement->theSize = theSize ;
  261.             unsigned long size = Q3Size_Pad ( theSize ) ;
  262.             toInternalElement->theHandle = NewHandleClear ( size ) ;
  263.             if (toInternalElement->theHandle)
  264.                 {
  265.                 BlockMoveData ( *(fromAPIElement->theHandle) , *(toInternalElement->theHandle) , theSize ) ;
  266.                 return kQ3Success ;
  267.                 }
  268.             else
  269.                 return kQ3Failure ;
  270.             }
  271.         else
  272.             {
  273.             toInternalElement->theHandle = nil ;
  274.             toInternalElement->theSize = 0 ;
  275.             return kQ3Failure ;
  276.             }
  277.         }
  278.     return kQ3Success ;
  279.     }
  280.  
  281.  
  282. TQ3Status HandleCopyReplace ( const THandleRecord* fromAPIElement , THandleRecord* toInternalElement )
  283.     {
  284.     if ( fromAPIElement && toInternalElement )
  285.         {
  286.         if ( toInternalElement->theHandle )
  287.             DisposeHandle ( toInternalElement->theHandle ) ;
  288.         return HandleCopyAdd ( fromAPIElement , toInternalElement ) ;
  289.         }
  290.     return kQ3Success ;
  291.     }
  292.  
  293.  
  294. TQ3Status HandleDelete ( THandleRecord* internalElement )
  295.     {
  296.     if ( internalElement )
  297.         {
  298.         if ( internalElement->theHandle )
  299.             {
  300.             DisposeHandle ( internalElement->theHandle ) ;
  301.             internalElement->theHandle = nil ;
  302.             }
  303.         internalElement->theSize = 0 ;
  304.         }
  305.     return kQ3Success ;
  306.     }
  307.  
  308.  
  309. //------------------------------------------------------------------------------------------------
  310.  
  311. TQ3ObjectClass RegisterSoundAttribute ( void )
  312.     {
  313.     return RegisterCustomAttribute ( kCustomSoundType , sizeof ( THandleRecord ) , SoundMetaHandler ) ;
  314.     }
  315.  
  316.  
  317. TQ3FunctionPointer SoundMetaHandler ( TQ3MethodType methodType )
  318.     {
  319.     return HandleRecordMetaHandler ( methodType , (TQ3FunctionPointer)SoundReadData ) ;
  320.     }
  321.  
  322.  
  323. TQ3Status SoundReadData ( TQ3SetObject parentObject , TQ3FileObject file )
  324.     {
  325.     if ( parentObject && file )
  326.         {
  327.         THandleRecord theHandleRec ;
  328.         if ( DoHandleReadData ( theHandleRec , file ) )
  329.             return Q3AttributeSet_Add ( parentObject , kCustomSoundType , &theHandleRec ) ;
  330.         else
  331.             return kQ3Failure ;
  332.         }
  333.     return kQ3Failure ;
  334.     }
  335.  
  336. //------------------------------------------------------------------------------------------------
  337.  
  338. TQ3ObjectClass RegisterPictAttribute ( void )
  339.     {
  340.     return RegisterCustomAttribute ( kCustomPictType , sizeof ( THandleRecord ) , PictMetaHandler ) ;
  341.     }
  342.  
  343.  
  344. TQ3FunctionPointer PictMetaHandler ( TQ3MethodType methodType )
  345.     {
  346.     return HandleRecordMetaHandler ( methodType , (TQ3FunctionPointer)PictReadData ) ;
  347.     }
  348.  
  349.  
  350. TQ3Status PictReadData ( TQ3SetObject parentObject , TQ3FileObject file )
  351.     {
  352.     if ( parentObject && file )
  353.         {
  354.         THandleRecord theHandleRec ;
  355.         if ( DoHandleReadData ( theHandleRec , file ) )
  356.             return Q3AttributeSet_Add ( parentObject , kCustomPictType , &theHandleRec ) ;
  357.         else
  358.             return kQ3Failure ;
  359.         }
  360.     return kQ3Failure ;
  361.     }
  362.  
  363. //------------------------------------------------------------------------------------------------
  364.  
  365. TQ3ObjectClass RegisterTextAttribute ( void )
  366.     {
  367.     return RegisterCustomAttribute ( kCustomTextType , sizeof ( THandleRecord ) , TextMetaHandler ) ;
  368.     }
  369.  
  370.  
  371. TQ3FunctionPointer TextMetaHandler ( TQ3MethodType methodType )
  372.     {
  373.     return HandleRecordMetaHandler ( methodType , (TQ3FunctionPointer)TextReadData ) ;
  374.     }
  375.  
  376.  
  377. TQ3Status TextReadData ( TQ3SetObject parentObject , TQ3FileObject file )
  378.     {
  379.     if ( parentObject && file )
  380.         {
  381.         THandleRecord theHandleRec ;
  382.         if ( DoHandleReadData ( theHandleRec , file ) )
  383.             return Q3AttributeSet_Add ( parentObject , kCustomTextType , &theHandleRec ) ;
  384.         else
  385.             return kQ3Failure ;
  386.         }
  387.     return kQ3Failure ;
  388.     }
  389.  
  390. //------------------------------------------------------------------------------------------------
  391.  
  392. TQ3ObjectClass RegisterMovieAttribute ( void )
  393.     {
  394.     return RegisterCustomAttribute ( kCustomMovieType , sizeof ( THandleRecord ) , MovieMetaHandler ) ;
  395.     }
  396.  
  397.  
  398. TQ3FunctionPointer MovieMetaHandler ( TQ3MethodType methodType )
  399.     {
  400.     return HandleRecordMetaHandler ( methodType , (TQ3FunctionPointer)MovieReadData ) ;
  401.     }
  402.  
  403.  
  404. TQ3Status MovieReadData ( TQ3SetObject parentObject , TQ3FileObject file )
  405.     {
  406.     if ( parentObject && file )
  407.         {
  408.         THandleRecord theHandleRec ;
  409.         if ( DoHandleReadData ( theHandleRec , file ) )
  410.             return Q3AttributeSet_Add ( parentObject , kCustomMovieType , &theHandleRec ) ;
  411.         else
  412.             return kQ3Failure ;
  413.         }
  414.     return kQ3Failure ;
  415.     }
  416.  
  417. //------------------------------------------------------------------------------------------------
  418.  
  419. TQ3ObjectClass RegisterDescriptionAttribute ( void )
  420.     {
  421.     return RegisterCustomAttribute ( kDescriptionAttribute , sizeof ( THandleRecord ) , DescriptionMetaHandler ) ;
  422.     }
  423.  
  424.  
  425. TQ3FunctionPointer DescriptionMetaHandler ( TQ3MethodType methodType )
  426.     {
  427.     return HandleRecordMetaHandler ( methodType , (TQ3FunctionPointer)DescriptionReadData ) ;
  428.     }
  429.  
  430.  
  431. TQ3Status DescriptionReadData ( TQ3SetObject parentObject , TQ3FileObject file )
  432.     {
  433.     if ( parentObject && file )
  434.         {
  435.         THandleRecord theHandleRec ;
  436.         if ( DoHandleReadData ( theHandleRec , file ) )
  437.             return Q3AttributeSet_Add ( parentObject , kDescriptionAttribute , &theHandleRec ) ;
  438.         else
  439.             return kQ3Failure ;
  440.         }
  441.     return kQ3Failure ;
  442.     }
  443.  
  444. //------------------------------------------------------------------------------------------------
  445.  
  446.  
  447. TQ3FunctionPointer FourByteMetaHandler ( TQ3MethodType methodType )
  448.     {
  449.     switch ( methodType )
  450.         {
  451.         case kQ3MethodTypeObjectTraverse:
  452.             return (TQ3FunctionPointer)FourByteTraverse ;
  453.             
  454.         case kQ3MethodTypeObjectWrite:
  455.             return (TQ3FunctionPointer)FourByteWrite ;
  456.             
  457.         case kQ3MethodTypeObjectReadData:
  458.             return (TQ3FunctionPointer)FourByteRead ;
  459.         
  460.         case kQ3MethodTypeElementCopyAdd:
  461.         case kQ3MethodTypeElementCopyGet:
  462.         case kQ3MethodTypeElementCopyDuplicate:
  463.         case kQ3MethodTypeElementCopyReplace:
  464.             return (TQ3FunctionPointer)FourByteCopy ;
  465.             
  466.         default:
  467.             return nil ;
  468.         } // switch
  469.     }
  470.  
  471.  
  472. TQ3Status FourByteTraverse ( TQ3Object , unsigned long* data , TQ3ViewObject view )
  473.     {
  474.     return Q3View_SubmitWriteData ( view , sizeof ( unsigned long ) , data , nil ) ;
  475.     }
  476.  
  477.  
  478. TQ3Status FourByteWrite ( const unsigned long* data , TQ3FileObject file )
  479.     {
  480.     return Q3Uns32_Write ( *data , file ) ;
  481.     }
  482.  
  483.  
  484. TQ3Status FourByteRead ( TQ3Object parentObject , TQ3FileObject file )
  485.     {
  486.     if ( parentObject && file )
  487.         {
  488.         unsigned long data ;
  489.         TQ3Status err = Q3Uns32_Read ( &data , file ) ;
  490.         if ( err == kQ3Success )
  491.             err = Q3AttributeSet_Add ( parentObject , kLockedAttribute , &data ) ;
  492.         return err ;
  493.         }
  494.     return kQ3Failure ;
  495.     }
  496.  
  497.  
  498. TQ3Status FourByteCopy ( const unsigned long* fromAPIElement , unsigned long* toInternalElement )
  499.     {
  500.     if ( toInternalElement && fromAPIElement )
  501.         *toInternalElement = *fromAPIElement ;
  502.     return kQ3Success ;
  503.     }
  504.  
  505.  
  506. //------------------------------------------------------------------------------------------------
  507.  
  508.  
  509. TQ3ObjectClass RegisterLockedAttribute ( void )
  510.     {
  511.     return RegisterCustomAttribute ( kLockedAttribute , sizeof ( long ) , FourByteMetaHandler ) ;
  512.     }
  513.  
  514.  
  515. //------------------------------------------------------------------------------------------------
  516.  
  517.  
  518. TQ3FunctionPointer DoubleMetaHandler ( TQ3MethodType methodType )
  519.     {
  520.     switch ( methodType )
  521.         {
  522.         case kQ3MethodTypeObjectTraverse:
  523.             return (TQ3FunctionPointer)DoubleTraverse ;
  524.             
  525.         case kQ3MethodTypeObjectWrite:
  526.             return (TQ3FunctionPointer)DoubleWrite ;
  527.             
  528.         case kQ3MethodTypeObjectReadData:
  529.             return (TQ3FunctionPointer)DoubleRead ;
  530.             
  531.         case kQ3MethodTypeElementCopyAdd:
  532.         case kQ3MethodTypeElementCopyGet:
  533.         case kQ3MethodTypeElementCopyDuplicate:
  534.         case kQ3MethodTypeElementCopyReplace:
  535.             return (TQ3FunctionPointer)DoubleCopy ;
  536.             
  537.         default:
  538.             return nil ;
  539.         } // switch
  540.     }
  541.  
  542.  
  543. TQ3Status DoubleTraverse ( TQ3Object , TQ3Float64* data , TQ3ViewObject view )
  544.     {
  545.     if ( data == nil )
  546.         return kQ3Success ;
  547.     return Q3View_SubmitWriteData ( view , sizeof ( TQ3Float64 ) , data , nil ) ;
  548.     }
  549.  
  550.  
  551. TQ3Status DoubleWrite ( const TQ3Float64* data , TQ3FileObject file )
  552.     {
  553. // no need to check data again as this will not be called it it is.
  554.     return Q3Float64_Write ( *data , file ) ;
  555.     }
  556.  
  557.  
  558. TQ3Status DoubleRead ( TQ3SetObject parentObject , TQ3FileObject file )
  559.     {
  560.     if ( parentObject && file )
  561.         {
  562.         double data ;
  563.         TQ3Status err = Q3Float64_Read ( &data , file ) ;
  564.         if ( err == kQ3Success )
  565.             err = Q3AttributeSet_Add ( parentObject , kUnitsAttribute , &data ) ;
  566.         return err;
  567.         }
  568.     return kQ3Failure ;
  569.     }
  570.  
  571.  
  572. TQ3Status DoubleCopy ( const double* fromAPIElement , double* toInternalElement )
  573.     {
  574.     if ( toInternalElement && fromAPIElement )
  575.         *toInternalElement = *fromAPIElement ;
  576.     return kQ3Success ;
  577.     }
  578.  
  579.  
  580. TQ3ObjectClass RegisterUnitsAttribute ( void )
  581.     {
  582.     return RegisterCustomAttribute ( kUnitsAttribute , sizeof ( TQ3Float64 ) , DoubleMetaHandler ) ;
  583.     }
  584.  
  585.  
  586. TQ3ObjectClass RegisterScaleAttribute ( void )
  587.     {
  588.     return RegisterCustomAttribute ( kScaleAttribute , sizeof ( TQ3Float64 ) , DoubleMetaHandler ) ;
  589.     }
  590.  
  591.  
  592. //------------------------------------------------------------------------------------------------
  593.  
  594.  
  595. TQ3FunctionPointer NameMetaHandler ( TQ3MethodType methodType )
  596.     {
  597.     switch ( methodType )
  598.         {
  599.         case kQ3MethodTypeObjectTraverse:
  600.             return (TQ3FunctionPointer)HandleNameTraverse ;
  601.             
  602.         case kQ3MethodTypeObjectWrite:
  603.             return (TQ3FunctionPointer)HandleNameWrite ;
  604.             
  605.         case kQ3MethodTypeObjectReadData:
  606.             return (TQ3FunctionPointer)HandleNameReadData ;
  607.             
  608.         case kQ3MethodTypeElementCopyAdd:
  609.         case kQ3MethodTypeElementCopyGet:
  610.         case kQ3MethodTypeElementCopyDuplicate:
  611.             return (TQ3FunctionPointer)HandleNameCopyAdd ;
  612.             
  613.         case kQ3MethodTypeElementCopyReplace:
  614.             return (TQ3FunctionPointer)HandleNameCopyReplace ;
  615.             
  616.         case kQ3MethodTypeElementDelete:
  617.             return (TQ3FunctionPointer)HandleNameDelete ;
  618.             
  619.         default:
  620.             return nil ;
  621.         } // switch
  622.     }
  623.  
  624.  
  625. //------------------------------------------------------------------------------------------------
  626.  
  627.  
  628. TQ3Status HandleNameTraverse ( TQ3Object /*object*/ , TQ3Object* theStringObj , TQ3ViewObject theView )
  629.     {
  630.     if (*theStringObj == nil)
  631.         return kQ3Success ;
  632.     unsigned long length ;
  633.     if ( Q3CString_GetLength ( *theStringObj , &length ) == kQ3Success )
  634.         {
  635.         char* namePtr = nil ;
  636.         if ( Q3CString_GetString ( *theStringObj , &namePtr ) == kQ3Success )
  637.             {
  638.             if ( namePtr && theView )
  639.                 {
  640.                 length = Q3Size_Pad ( length + 1 ) ;
  641.                 return Q3View_SubmitWriteData ( theView , length , namePtr , NULL ) ;
  642.                 }
  643.             }
  644.         }
  645.     return kQ3Failure ;
  646.     }
  647.  
  648.  
  649. TQ3Status HandleNameWrite ( const char* data , TQ3FileObject file )
  650.     {
  651.     if ( data && file )
  652.         return Q3String_Write ( data , file ) ;
  653.     else
  654.         return kQ3Failure ;
  655.     }    
  656.  
  657.  
  658. TQ3Status HandleNameReadData ( TQ3Object parentObject , TQ3FileObject file )
  659.     {
  660.     if ( parentObject && file )
  661.         {
  662.         Ptr data = NewPtrClear ( kQ3StringMaximumLength ) ;
  663.         if ( data )
  664.             {
  665.             unsigned long length = 0 ;
  666.             TQ3Status err = Q3String_Read ( (char*)data , &length , file ) ;
  667.             if ( err == kQ3Success )
  668.                 {
  669.                 TQ3Object theObj = Q3CString_New ( data ) ;
  670.                 if ( theObj )
  671.                     {
  672.                     err = Q3AttributeSet_Add ( parentObject , kNameAttribute , &theObj ) ;
  673.                     Q3Object_Dispose ( theObj ) ;
  674.                     }
  675.                 else
  676.                     err = kQ3Failure ;
  677.                 }
  678.             DisposePtr ( data ) ;
  679.             return err ;
  680.             }
  681.         }
  682.     return kQ3Failure ;
  683.     }
  684.     
  685.     
  686. TQ3Status HandleNameCopyAdd ( const TQ3Object* fromAPIElement , TQ3Object* toInternalElement )
  687.     {
  688.     if ( toInternalElement && fromAPIElement )
  689.         {
  690.         *toInternalElement = Q3Object_Duplicate ( *fromAPIElement ) ;
  691.         if ( *toInternalElement )
  692.             return kQ3Success ;
  693.         }
  694.     return kQ3Success ;
  695.     }
  696.  
  697.  
  698. TQ3Status HandleNameCopyReplace ( const TQ3Object* fromAPIElement , TQ3Object* toInternalElement )
  699.     {
  700.     if ( toInternalElement && fromAPIElement )
  701.         {
  702.     /*
  703.         It is always good form to get a reference first,
  704.         in case src and dst point to the same object
  705.     */
  706.         TQ3Object temp = *toInternalElement ;
  707.         *toInternalElement = Q3Object_Duplicate ( *fromAPIElement ) ;
  708.         Q3Object_Dispose ( temp ) ;
  709.         if ( *toInternalElement )
  710.             return kQ3Success ;
  711.         }
  712.     return kQ3Success ;
  713.     }
  714.  
  715.  
  716. TQ3Status HandleNameDelete ( TQ3Object* internalElement )
  717.     {
  718.     if ( internalElement )
  719.         return Q3Object_Dispose ( *internalElement ) ; ;
  720.     return kQ3Success ;
  721.     }
  722.  
  723.  
  724. TQ3ObjectClass RegisterNameAttribute ( void )
  725.     {
  726.     return RegisterCustomAttribute ( kNameAttribute , sizeof ( TQ3StringObject ) , NameMetaHandler ) ;
  727.     }
  728.  
  729.  
  730. //------------------------------------------------------------------------------------------------
  731.  
  732.  
  733. TQ3Status VectorTraverse ( TQ3Object , TQ3Vector3D* upVector , TQ3ViewObject view )
  734.     {
  735.     if ( upVector && view )
  736.         return Q3View_SubmitWriteData ( view , sizeof ( TQ3Vector3D ) , upVector , nil ) ;
  737.     return kQ3Success ;
  738.     }
  739.  
  740.  
  741. TQ3Status VectorWrite ( const TQ3Vector3D* upVector, TQ3FileObject file )
  742.     {
  743.     if ( upVector && file )
  744.         return Q3Vector3D_Write(upVector, file);
  745.     return kQ3Failure ;
  746.     }
  747.  
  748.  
  749. TQ3Status UpVectorAttributeReadData ( TQ3SetObject attributeSet , TQ3FileObject file )
  750.     {
  751.     if ( attributeSet && file )
  752.         {
  753.         TQ3Vector3D upVector ;
  754.         if ( Q3Vector3D_Read ( &upVector , file ) == kQ3Failure )
  755.             return kQ3Failure ;
  756.         return Q3Set_Add ( attributeSet , kUpVectorAttribute , &upVector ) ;
  757.         }
  758.     return kQ3Failure ;
  759.     }
  760.  
  761.  
  762. TQ3FunctionPointer UpVectorAttributeMetaHandler ( TQ3MethodType methodType )
  763.     {
  764.     switch ( methodType )
  765.         {
  766.         case kQ3MethodTypeObjectTraverse :
  767.             return (TQ3FunctionPointer) VectorTraverse ;
  768.         case kQ3MethodTypeObjectWrite :
  769.             return (TQ3FunctionPointer) VectorWrite ;
  770.         case kQ3MethodTypeObjectReadData :
  771.             return (TQ3FunctionPointer) UpVectorAttributeReadData ;
  772.         default :
  773.             return (TQ3FunctionPointer) nil ;
  774.         }
  775.     }
  776.  
  777.  
  778. TQ3ObjectClass RegisterUpVectorAttribute ( void )
  779.     {
  780.     return RegisterCustomAttribute ( kUpVectorAttribute , sizeof ( TQ3Vector3D ) , UpVectorAttributeMetaHandler ) ;
  781.     }
  782.  
  783.  
  784. TQ3Status ForwardDirectionAttributeReadData ( TQ3SetObject attributeSet , TQ3FileObject file )
  785.     {
  786.     if ( attributeSet && file )
  787.         {
  788.         TQ3Vector3D forwardDirection ;
  789.         if ( Q3Vector3D_Read ( &forwardDirection , file ) == kQ3Failure )
  790.             return kQ3Failure ;
  791.         return Q3Set_Add ( attributeSet , kForwardDirectionAttribute , &forwardDirection ) ;
  792.         }
  793.     return kQ3Failure ;
  794.     }
  795.  
  796.  
  797. TQ3FunctionPointer ForwardDirectionAttributeMetaHandler ( TQ3MethodType methodType )
  798.     {
  799.     switch ( methodType )
  800.         {
  801.         case kQ3MethodTypeObjectTraverse :
  802.             return (TQ3FunctionPointer) VectorTraverse ;
  803.         case kQ3MethodTypeObjectWrite :
  804.             return (TQ3FunctionPointer) VectorWrite ;
  805.         case kQ3MethodTypeObjectReadData :
  806.             return (TQ3FunctionPointer) ForwardDirectionAttributeReadData ;
  807.         default :
  808.             return (TQ3FunctionPointer) nil;
  809.         }
  810.     }
  811.  
  812. TQ3ObjectClass RegisterForwardDirectionAttribute ( void )
  813.     {
  814.     return RegisterCustomAttribute ( kForwardDirectionAttribute , sizeof ( TQ3Vector3D ) , ForwardDirectionAttributeMetaHandler ) ;
  815.     }
  816.  
  817.  
  818. //------------------------------------------------------------------------------------------------
  819. // World Wide Web Custom Attributes
  820. //------------------------------------------------------------------------------------------------
  821.  
  822.  
  823. TQ3Status W3AnchorTraverse ( TQ3Object , W3AnchorData* URLdata , TQ3ViewObject view )
  824.     {
  825.     if ( URLdata )
  826.         {
  827.         if ( URLdata->url == nil )
  828.             return kQ3Success ;
  829.         
  830.         TQ3Size size = Q3Size_Pad ( strlen ( URLdata->url ) + 1 ) ;
  831.         size += sizeof ( TQ3Uns32 ) ;
  832.         
  833.         if ( Q3View_SubmitWriteData ( view , size , URLdata , nil ) == kQ3Failure )
  834.             return kQ3Failure ;
  835.         
  836.         if ( URLdata->description )
  837.             {
  838.             if ( Q3Object_Submit ( URLdata->description , view ) == kQ3Failure )
  839.                 return kQ3Failure ;
  840.             }
  841.         }
  842.     return kQ3Success ;
  843.     }
  844.  
  845.  
  846. TQ3Status W3AnchorWrite ( const W3AnchorData* URLdata , TQ3FileObject file )
  847.     {
  848.     if ( URLdata && file )
  849.         return    ( Q3String_Write ( URLdata->url , file ) == kQ3Success ) &&
  850.                 ( Q3Uns32_Write ( (unsigned long) URLdata->options , file ) == kQ3Success  ) ? kQ3Success : kQ3Failure ;
  851.     return kQ3Success ;
  852.     }
  853.  
  854.  
  855. TQ3Status W3AnchorReadData ( TQ3SetObject set , TQ3FileObject file )
  856.     {
  857.     if ( set && file )
  858.         {
  859.         char            buf [ kQ3StringMaximumLength ] ;
  860.         W3AnchorData    URLData = { nil , nil , kW3AnchorOptionNone } ;
  861.         
  862.         if ( Q3String_Read ( buf , nil , file ) == kQ3Failure )
  863.             return kQ3Failure ;
  864.     
  865.         URLData.url = NewPtr ( strlen ( buf ) + 1 ) ;
  866.         strcpy ( URLData.url , buf ) ;
  867.         
  868.         if ( Q3Uns32_Read ( (unsigned long *) &URLData.options , file ) == kQ3Failure )
  869.             return kQ3Failure ;
  870.         
  871.         if ( Q3File_IsEndOfContainer ( file , NULL ) == kQ3False )
  872.             URLData.description = Q3File_ReadObject ( file ) ;
  873.         
  874.         return Q3Set_Add ( set , kW3AnchorAttribute , &URLData ) ;
  875.         }
  876.     return kQ3Failure ;
  877.     }
  878.  
  879.  
  880. TQ3Status W3AnchorCopyAdd ( const W3AnchorData* src , W3AnchorData* dst )
  881.     {
  882.     if ( src && dst )
  883.         {
  884.         if ( src->url == nil )
  885.             return kQ3Failure ;
  886.     
  887.         long i = strlen ( src->url ) ;
  888.         if ( i == 0 )
  889.             return kQ3Failure ;
  890.         
  891.         dst->url = NewPtr ( i + 1 ) ;
  892.         if ( dst->url == nil )
  893.             return kQ3Failure ;
  894.             
  895.         strcpy ( dst->url , src->url ) ;
  896.         if ( src->description )
  897.             dst->description = Q3Object_Duplicate ( src->description ) ;
  898.         else
  899.             dst->description = nil ;            
  900.         dst->options = src->options ;
  901.         }
  902.     return kQ3Success ;
  903.     }
  904.  
  905.  
  906. TQ3Status W3AnchorCopyReplace ( const W3AnchorData* src , W3AnchorData* dst )
  907.     {
  908.     if ( src && dst )
  909.         {
  910.         if ( src->url == nil )
  911.             return kQ3Failure ;
  912.     
  913.         long i = strlen ( src->url ) ;
  914.         if ( i == 0 )
  915.             return kQ3Failure ;
  916.         char* c = NewPtr ( i + 1 ) ;
  917.         if ( c == nil )
  918.             return kQ3Failure ;
  919.         dst->url = c ;
  920.         strcpy ( dst->url , src->url ) ;
  921.         
  922.         TQ3Object temp = dst->description ;            
  923.         if ( src->description )
  924.             dst->description = Q3Object_Duplicate (src->description);
  925.         else
  926.             dst->description = nil ;
  927.         if ( temp )
  928.             Q3Object_Dispose ( temp ) ;            
  929.         dst->options = src->options ;
  930.         }
  931.     return kQ3Success ;
  932.     }
  933.  
  934.  
  935. TQ3Status W3AnchorDelete ( W3AnchorData* URLData )
  936.     {
  937.     if ( URLData )
  938.         {
  939.         if ( URLData->url ) 
  940.             DisposePtr ( URLData->url ) ;
  941.         if ( URLData->description ) 
  942.             Q3Object_Dispose ( URLData->description ) ;
  943.         }
  944.     return kQ3Success ;
  945.     }
  946.  
  947.  
  948. TQ3FunctionPointer W3AnchorMetaHandler ( TQ3MethodType methodType )
  949.     {
  950.     switch ( methodType )
  951.         {
  952.         case kQ3MethodTypeObjectTraverse :
  953.             return (TQ3FunctionPointer) W3AnchorTraverse ;
  954.         case kQ3MethodTypeObjectWrite :
  955.             return (TQ3FunctionPointer) W3AnchorWrite ;
  956.         case kQ3MethodTypeObjectReadData :
  957.             return (TQ3FunctionPointer) W3AnchorReadData ;
  958.         case kQ3MethodTypeElementCopyAdd :
  959.         case kQ3MethodTypeElementCopyGet :
  960.         case kQ3MethodTypeElementCopyDuplicate :
  961.             return (TQ3FunctionPointer) W3AnchorCopyAdd ;
  962.         case kQ3MethodTypeElementCopyReplace :
  963.             return (TQ3FunctionPointer) W3AnchorCopyReplace ;
  964.         case kQ3MethodTypeElementDelete :
  965.             return (TQ3FunctionPointer) W3AnchorDelete ;
  966.         default :
  967.             return (TQ3FunctionPointer) nil ;
  968.         }
  969.     }
  970.  
  971.  
  972. TQ3ObjectClass RegisterW3Anchor ( void )
  973.     {
  974.     return RegisterCustomAttribute ( kW3AnchorAttribute , sizeof ( W3AnchorData ) , W3AnchorMetaHandler ) ;
  975.     }
  976.  
  977.  
  978. //------------------------------------------------------------------------------------------------
  979.  
  980.  
  981. TQ3Status W3InlineTraverse ( TQ3Object , W3InlineData* inlineData , TQ3ViewObject view )
  982.     {
  983.     if ( inlineData && view )
  984.         {
  985.         if ( inlineData->url == nil )
  986.             return kQ3Success ;
  987.         TQ3Size size = Q3Size_Pad ( strlen ( inlineData->url ) + 1 ) ;
  988.         return Q3View_SubmitWriteData ( view , size , inlineData , nil ) ;
  989.         }
  990.     return kQ3Success ;
  991.     }
  992.  
  993.  
  994. TQ3Status W3InlineWrite ( const W3InlineData* inlineData , TQ3FileObject file )
  995.     {
  996.     if ( inlineData && file )
  997.         return    Q3String_Write ( inlineData->url , file ) == kQ3Success &&
  998.                 Q3Comment_Write ( "url" , file ) == kQ3Success ? kQ3Success : kQ3Failure ;
  999.     return kQ3Success ;
  1000.     }
  1001.  
  1002.  
  1003. TQ3Status W3InlineReadData ( TQ3SetObject set , TQ3FileObject file )
  1004.     {
  1005.     if ( set && file )
  1006.         {
  1007.         char            buf [ kQ3StringMaximumLength ] ;
  1008.         W3InlineData    inlineData ;
  1009.         if ( Q3String_Read ( buf , nil , file ) == kQ3Failure )
  1010.             return kQ3Failure ;
  1011.         inlineData.url = buf ;
  1012.         return Q3Set_Add ( set , kW3InlineAttribute , &inlineData ) ;
  1013.         }
  1014.     return kQ3Failure ;
  1015.     }
  1016.  
  1017.  
  1018. TQ3Status W3InlineCopyAdd ( const W3InlineData* src , W3InlineData* dst )
  1019.     {
  1020.     if ( src && dst )
  1021.         {
  1022.         if ( src->url == nil )
  1023.             return kQ3Failure ;
  1024.         long i = strlen ( src->url ) ;
  1025.         if ( i == 0 )
  1026.             return kQ3Failure ;
  1027.         dst->url = NewPtr ( i + 1 ) ;
  1028.         if ( dst->url == nil )
  1029.             return kQ3Failure ;
  1030.         strcpy ( dst->url , src->url ) ;
  1031.         }
  1032.     return kQ3Success ;
  1033.     }
  1034.  
  1035.  
  1036. TQ3Status W3InlineCopyReplace ( const W3InlineData* src , W3InlineData* dst )
  1037.     {
  1038.     if ( src && dst )
  1039.         {
  1040.         if ( src->url == nil )
  1041.             return kQ3Failure ;
  1042.         long i = strlen ( src->url ) ;
  1043.         if ( i == 0 )
  1044.             return kQ3Failure ;
  1045.         char* c = NewPtr ( i + 1 ) ;
  1046.         if ( c == nil )
  1047.             return kQ3Failure ;
  1048.         dst->url = c ;
  1049.         strcpy ( dst->url , src->url ) ;
  1050.         }
  1051.     return kQ3Success ;
  1052.     }
  1053.  
  1054.  
  1055. TQ3Status W3InlineDelete ( W3InlineData* src )
  1056.     {
  1057.     if ( src && src->url ) 
  1058.         DisposePtr ( src->url ) ;
  1059.     return kQ3Success ;
  1060.     }
  1061.  
  1062.  
  1063. TQ3FunctionPointer W3InlineMetaHandler ( TQ3MethodType methodType )
  1064.     {
  1065.     switch ( methodType )
  1066.         {
  1067.         case kQ3MethodTypeObjectTraverse :
  1068.             return (TQ3FunctionPointer) W3InlineTraverse ;
  1069.         case kQ3MethodTypeObjectWrite :
  1070.             return (TQ3FunctionPointer) W3InlineWrite ;
  1071.         case kQ3MethodTypeObjectReadData :
  1072.             return (TQ3FunctionPointer) W3InlineReadData ;
  1073.         case kQ3MethodTypeElementCopyAdd:
  1074.         case kQ3MethodTypeElementCopyGet:
  1075.         case kQ3MethodTypeElementCopyDuplicate :
  1076.             return (TQ3FunctionPointer) W3InlineCopyAdd ;
  1077.         case kQ3MethodTypeElementCopyReplace :
  1078.             return (TQ3FunctionPointer) W3InlineCopyReplace ;
  1079.         case kQ3MethodTypeElementDelete :
  1080.             return (TQ3FunctionPointer) W3InlineDelete ;
  1081.         default :
  1082.             return (TQ3FunctionPointer) nil ;
  1083.         }
  1084.     }
  1085.  
  1086.  
  1087. TQ3ObjectClass RegisterW3Inline ( void )
  1088.     {
  1089.     return RegisterCustomAttribute ( kW3InlineAttribute , sizeof ( W3InlineData ) , W3InlineMetaHandler ) ;
  1090.     }
  1091.  
  1092.  
  1093. /***********************************************************************************************
  1094. *
  1095. *    This one is obsolete.  The code below will convert to the new type on reading and writing
  1096. *
  1097. ***********************************************************************************************/
  1098.  
  1099. TQ3Status WWWAnchorTraverse ( TQ3Object , WWWAnchorData* wwwdata , TQ3ViewObject view )
  1100.     {
  1101.     if ( wwwdata && wwwdata->url )
  1102.         {
  1103.         TQ3Size size = Q3Size_Pad ( strlen ( wwwdata->url ) + 1 ) ;
  1104.         return Q3View_SubmitWriteData ( view , size , wwwdata , nil ) ;
  1105.         }
  1106.     return kQ3Success ;
  1107.     }
  1108.  
  1109.  
  1110. TQ3Status WWWAnchorWrite ( const WWWAnchorData *wwwdata , TQ3FileObject file )
  1111.     {
  1112.     if ( wwwdata && file )
  1113.         return  Q3String_Write ( wwwdata->url , file ) == kQ3Success &&
  1114.                 Q3Comment_Write ( "url" , file ) == kQ3Success ? kQ3Success : kQ3Failure ;
  1115.     return kQ3Failure ;
  1116.     }
  1117.  
  1118.  
  1119. TQ3Status WWWAnchorReadData ( TQ3SetObject set , TQ3FileObject file )
  1120.     {
  1121.     if ( set && file )
  1122.         {
  1123.         char                buf [ kQ3StringMaximumLength] ;
  1124.         WWWAnchorData        wwwdata ;
  1125.         W3AnchorData        W3Anchor ;
  1126.         
  1127.         if ( Q3String_Read ( buf, nil , file ) == kQ3Failure )
  1128.             return kQ3Failure ;
  1129.     
  1130.         wwwdata.url = NewPtr ( strlen ( buf ) + 1 ) ;
  1131.         strcpy ( wwwdata.url, buf ) ;
  1132.     
  1133.         W3Anchor.url = NewPtr ( strlen ( buf ) + 1 ) ;
  1134.         strcpy ( W3Anchor.url , buf ) ;
  1135.          
  1136.          W3Anchor.description = nil ;
  1137.          W3Anchor.options = kW3AnchorOptionNone ;
  1138.          
  1139.          Q3Set_Add ( set , kW3AnchorAttribute , &W3Anchor ) ;
  1140.          
  1141.         return Q3Set_Add ( set , kElementTypeWWWAnchor , &wwwdata ) ;
  1142.         }
  1143.     return kQ3Failure ;
  1144.     }
  1145.  
  1146.  
  1147. TQ3Status WWWAnchorCopyAdd ( const WWWAnchorData* src , WWWAnchorData* dst )
  1148.     {
  1149.     if ( src && dst && src->url )
  1150.         {
  1151.         long i = strlen ( src->url ) ;
  1152.         if ( i == 0 )
  1153.             return kQ3Failure ;
  1154.         dst->url = NewPtr ( i + 1 ) ;
  1155.         if ( dst->url == nil )
  1156.             return kQ3Failure ;
  1157.         strcpy ( dst->url , src->url ) ;
  1158.         }
  1159.     return kQ3Success ;
  1160.     }
  1161.  
  1162.  
  1163. TQ3Status WWWAnchorCopyReplace ( const WWWAnchorData* src , WWWAnchorData* dst )
  1164.     {
  1165.     if ( src && dst && src->url )
  1166.         {
  1167.         long i = strlen ( src->url ) ;
  1168.         if ( i == 0 )
  1169.             return kQ3Failure ;
  1170.         char* c = NewPtr ( i + 1 ) ;
  1171.         if ( c == nil )
  1172.             return kQ3Failure ;
  1173.         dst->url = c ;
  1174.         strcpy ( dst->url , src->url ) ;
  1175.         }
  1176.     return kQ3Success ;
  1177.     }
  1178.  
  1179.  
  1180. TQ3Status WWWAnchorDelete ( WWWAnchorData* src )
  1181.     {
  1182.     if ( src && src->url ) 
  1183.         DisposePtr ( src->url ) ;
  1184.     return kQ3Success ;
  1185.     }
  1186.  
  1187.  
  1188. TQ3FunctionPointer WWWAnchorMetaHandler( TQ3MethodType methodType )
  1189.     {
  1190.     switch ( methodType )
  1191.         {
  1192.         case kQ3MethodTypeObjectTraverse :
  1193.             return (TQ3FunctionPointer) WWWAnchorTraverse ;
  1194.         case kQ3MethodTypeObjectWrite :
  1195.             return (TQ3FunctionPointer) WWWAnchorWrite ;
  1196.         case kQ3MethodTypeObjectReadData :
  1197.             return (TQ3FunctionPointer) WWWAnchorReadData ;
  1198.         case kQ3MethodTypeElementCopyAdd :
  1199.         case kQ3MethodTypeElementCopyGet :
  1200.         case kQ3MethodTypeElementCopyDuplicate :
  1201.             return (TQ3FunctionPointer) WWWAnchorCopyAdd ;
  1202.         case kQ3MethodTypeElementCopyReplace :
  1203.             return (TQ3FunctionPointer) WWWAnchorCopyReplace ;
  1204.         case kQ3MethodTypeElementDelete :
  1205.             return (TQ3FunctionPointer) WWWAnchorDelete ;
  1206.         default :
  1207.             return (TQ3FunctionPointer) nil ;
  1208.         }
  1209.     }
  1210.  
  1211.  
  1212. TQ3ObjectClass RegisterWWWAnchor ( void )
  1213.     {
  1214.     return RegisterCustomAttribute ( kElementTypeWWWAnchor , sizeof ( WWWAnchorData ) , WWWAnchorMetaHandler ) ;
  1215.     }
  1216.  
  1217.  
  1218. //------------------------------------------------------------------------------------------------
  1219.